package com.nuoniu.sibanyun.service.erp.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.lang.DateUtils;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.entity.bo.UsedGradeRuleBo;
import com.nuoniu.sibanyun.entity.dto.ErpGradeRuleDto;
import com.nuoniu.sibanyun.entity.erp.ErpGradeRule;
import com.nuoniu.sibanyun.mapper.erp.ErpGradeRuleMapper;
import com.nuoniu.sibanyun.service.erp.IErpAccountService;
import com.nuoniu.sibanyun.service.erp.IErpGradeRuleService;
import com.nuoniu.sibanyun.service.erp.in.IInWarehouseService;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author baiqiang
 * @since 2020-09-22
 */
@Service
public class ErpGradeRuleServiceImpl extends ServiceImpl<ErpGradeRuleMapper, ErpGradeRule> implements IErpGradeRuleService {


    @Autowired
    private IErpAccountService erpAccountService;

    @Autowired
    private IInWarehouseService inWarehouseService;


    @Override
    public void innitData(UserInfo userInfo, Integer accountId) {
        List<ErpGradeRule> erpGradeRules = listDefErpGradeRule();
        String yearStr = DateUtils.getYear();
        Integer year = Integer.valueOf(yearStr);
        if(erpGradeRules.size() > 0){
            erpGradeRules.forEach(f->{
                f.setCompanyId(userInfo.getCompanyId());
                f.setYear(year);
                f.setAccountId(accountId);
                f.setId(null);
            });
            saveBatch(erpGradeRules);
        }
    }

    @Override
    public List<ErpGradeRule> listDefErpGradeRule() {
        QueryWrapper<ErpGradeRule> erpGradeRuleQueryWrapper = new QueryWrapper<>();
        erpGradeRuleQueryWrapper.eq("company_id",1);
        erpGradeRuleQueryWrapper.eq("is_enable",1);
        erpGradeRuleQueryWrapper.eq("account_id",0);
        List<ErpGradeRule> list = list(erpGradeRuleQueryWrapper);
        return list;
    }

    @Override
    public List<ErpGradeRule> listAllErpGradeRule() {
        UserInfo userInfo = UserThreadLocal.get();
        //Integer currentAccountId = erpAccountService.getCurrentAccountId();
        QueryWrapper<ErpGradeRule> erpGradeRuleQueryWrapper = new QueryWrapper<>();
        erpGradeRuleQueryWrapper.eq("company_id",userInfo.getCompanyId());
        erpGradeRuleQueryWrapper.eq("is_enable",1);
        //erpGradeRuleQueryWrapper.eq("account_id",currentAccountId);
        List<ErpGradeRule> list = list(erpGradeRuleQueryWrapper);
        return list;
    }

    @Override
    public List<ErpGradeRule> listCurrentErpGradeRule(Integer accountId) {
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<ErpGradeRule> erpGradeRuleQueryWrapper = new QueryWrapper<>();
        erpGradeRuleQueryWrapper.eq("company_id",userInfo.getCompanyId());
        erpGradeRuleQueryWrapper.eq("is_enable",1);
        //erpGradeRuleQueryWrapper.eq("account_id",accountId);
        List<ErpGradeRule> list = list(erpGradeRuleQueryWrapper);
        return list;
    }

    @Override
    public void saveOrUpdateErpGradeRule(List<ErpGradeRuleDto> erpGradeRuleDtoList) {
        if(null == erpGradeRuleDtoList) {
            return;
        }
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        Map<String,ErpGradeRule> gradeRuleHashMap = new HashMap<>();
        List<ErpGradeRule> currentErpGradeRule = listCurrentErpGradeRule(currentAccountId);
        currentErpGradeRule.forEach(gradeRule->gradeRuleHashMap.put(gradeRule.getKeyword(),gradeRule));
        List<ErpGradeRule> erpGradeRuleList = new ArrayList<>();

        erpGradeRuleDtoList.forEach(dto->{
            ErpGradeRule erpGradeRule = gradeRuleHashMap.get(dto.getKeyword());
            if(null != erpGradeRule && StringUtils.isNotBlank(dto.getCodingRule()) && !dto.getCodingRule().equals(erpGradeRule.getCodingRule())){
                erpGradeRule.setCodingRule(dto.getCodingRule());
                // 校验 是否 可以修改
                checkGradeRule(erpGradeRule);
                erpGradeRuleList.add(erpGradeRule);
            }
        });
        if(erpGradeRuleList.size() > 0){
            updateBatchById(erpGradeRuleList);
        }

    }


    @Override
    public ErpGradeRule getCurrentYearErpGradeRuleByCode(String code) {
        if(StringUtils.isBlank(code)) {
            return null;
        }
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        if(null == currentAccountId) {
            throw new NuoNiuException("当前账套已经结算或者没有账套");
        }
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<ErpGradeRule> erpGradeRuleQueryWrapper = new QueryWrapper<>();
        erpGradeRuleQueryWrapper.eq("company_id",userInfo.getCompanyId());
        erpGradeRuleQueryWrapper.eq("account_id",currentAccountId);
        erpGradeRuleQueryWrapper.eq("keyword",code);
        erpGradeRuleQueryWrapper.eq("is_enable",1);
        erpGradeRuleQueryWrapper.last("LIMIT 1");
        ErpGradeRule one = getOne(erpGradeRuleQueryWrapper, false);
        return one;
    }

    @Override
    public UsedGradeRuleBo checkCode(String code, String parentCode, Integer parentLevel, String ruleCode) {
        UsedGradeRuleBo usedGradeRuleBo = new UsedGradeRuleBo();
        if(StringUtils.isBlank(code)) {
            throw new NuoNiuException("编码不能为空");
        }
        if(!StringUtils.isLetterDigit(code)) {
            throw new NuoNiuException("编码只能包含字母和数字");
        }
        try{
            //获取编码规则
            ErpGradeRule erpGradeRuleByCode = getCurrentYearErpGradeRuleByCode(ruleCode);
            if(null == erpGradeRuleByCode) {
                throw new NuoNiuException("编码规则错误");
            }
            String codingRule = erpGradeRuleByCode.getCodingRule();
            if(StringUtils.isBlank(codingRule)) {
                throw new NuoNiuException("编码规则错误");
            }
            codingRule = StringUtils.trim(codingRule);
            String[] split = codingRule.split("");

            //1.上级Id不为空
            if(StringUtils.isNotBlank(parentCode)){
                //截取 当前编码
                String currentLevelCode = StringUtils.substringAfter(code, parentCode);
                if(StringUtils.isBlank(currentLevelCode)) {
                    throw new NuoNiuException("编码规则错误");
                }
                //获取当前编码
                if(split.length > parentLevel ){
                    String currentLevelRuleNumStr = split[parentLevel];
                    Integer currentLevelRuleNum = Integer.valueOf(currentLevelRuleNumStr);
                    if(currentLevelRuleNum  != currentLevelCode.length()) {
                        throw new NuoNiuException("当前编码与编码规则不符");
                    }
                    //****  设置 使用的编码级次 ****
                    usedGradeRuleBo.setGradeRuleLevel(parentLevel + 1);
                    usedGradeRuleBo.setGradeRuleStr(codingRule.substring(0,parentLevel + 1));
                }else{
                    throw new NuoNiuException("当前编码已经超过最大级次");
                }

            }
            //2.上级Id为空
            else {
                String currentLevelRuleNumStr = split[0];
                Integer currentLevelRuleNum = Integer.valueOf(currentLevelRuleNumStr);
                if(currentLevelRuleNum  != code.length()) {
                    throw new NuoNiuException("当前编码与编码规则不符");
                }
                //****  设置 使用的编码级次 ****
                usedGradeRuleBo.setGradeRuleLevel(1);
                usedGradeRuleBo.setGradeRuleStr(codingRule.substring(0,1));
            }
        }catch (Exception e){
            if (e instanceof NuoNiuException){
                throw new NuoNiuException(((NuoNiuException) e).getMsg());
            }else{
                throw new NuoNiuException("参数错误");
            }
        }
        return usedGradeRuleBo;
    }

    @Override
    public void checkGradeRule(ErpGradeRule erpGradeRule) {
        String keyword = erpGradeRule.getKeyword();
        String title = erpGradeRule.getTitle();
        String codingRule = erpGradeRule.getCodingRule();
        UsedGradeRuleBo usedGradeRuleBo = null;
        String tableName = null;
        switch (keyword){
            //仓库编码
            case "warehouse":
                tableName = "scb_warehouse";
                break;
            //货位编码
            case "inventoryLocation":
                tableName = "scb_storagebin";
                break;
            //物料分类
            case "inventoryclass":
                tableName = "scb_material_category";
                break;
            //收发类别编
            case "rd_style":
                tableName = "scb_rd_style";
                break;
            //结算方式编码级次
            case "settlestyle":
                tableName = "fab_settle_style";
                break;
            //科目编码级次
            case "code":
                tableName = "fab_accounting";
                break;
            //科目编码级次
            case "inventoryCategoryId":
                tableName = "scb_inventory_class";
                break;
            default:throw new NuoNiuException(title +":系统配置错误，请联系管理员");
        }
        usedGradeRuleBo = getMaxRuleLevel(tableName);
        if(null != usedGradeRuleBo){
            String gradeRuleStr = usedGradeRuleBo.getGradeRuleStr();
            Integer gradeRuleLevel = usedGradeRuleBo.getGradeRuleLevel();
            if (!codingRule.startsWith(gradeRuleStr)) {
                throw new NuoNiuException(title +":编辑失败，前面"+ gradeRuleLevel +"级 已经使用");
            }
        }

    }

    @Override
    public UsedGradeRuleBo getMaxRuleLevel(String tableName) {
        if(StringUtils.isBlank(tableName)) {
            return null;
        }
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        UserInfo userInfo = UserThreadLocal.get();
        return baseMapper.getMaxRuleLevel(currentAccountId,userInfo.getCompanyId(),tableName);
    }
}
